function mxMultiplicity(source, type, attr, value, min, max, validNeighbors, countError, typeError,
	validNeighborsAllowed)
{
	this.source = source;
	this.type = type;
	this.attr = attr;
	this.value = value;
	this.min = (min != null) ? min : 0;
	this.max = (max != null) ? max : 'n';
	this.validNeighbors = validNeighbors;
	this.countError = mxResources.get(countError) || countError;
	this.typeError = mxResources.get(typeError) || typeError;
	this.validNeighborsAllowed = (validNeighborsAllowed != null) ? validNeighborsAllowed : true;
};
mxMultiplicity.prototype.type = null;
mxMultiplicity.prototype.attr = null;
mxMultiplicity.prototype.value = null;
mxMultiplicity.prototype.source = null;
mxMultiplicity.prototype.min = null;
mxMultiplicity.prototype.max = null;
mxMultiplicity.prototype.validNeighbors = null;
mxMultiplicity.prototype.validNeighborsAllowed = true;
mxMultiplicity.prototype.countError = null;
mxMultiplicity.prototype.typeError = null;
mxMultiplicity.prototype.check = function(graph, edge, source, target, sourceOut, targetIn)
{
	var sourceValue = graph.model.getValue(source);
	var targetValue = graph.model.getValue(target);
	var error = '';

	if ((this.source && this.checkType(graph, sourceValue, this.type, this.attr, this.value))
		|| (!this.source && this.checkType(graph, targetValue, this.type, this.attr, this.value)))
	{
		if (this.countError != null && ((this.source && (this.max == 0 || (sourceOut >= this.max)))
			|| (!this.source && (this.max == 0 || (targetIn >= this.max)))))
		{
			error += this.countError + '\n';
		}
		var valid = this.validNeighbors;

		if (valid != null && valid.length > 0)
		{
			var isValid = !this.validNeighborsAllowed;

			for (var j = 0; j < valid.length; j++)
			{
				if (this.source && this.checkType(graph, targetValue, valid[j]))
				{
					isValid = this.validNeighborsAllowed;
					break;
				}
				else if (!this.source && this.checkType(graph, sourceValue, valid[j]))
				{
					isValid = this.validNeighborsAllowed;
					break;
				}
			}

			if (!isValid && this.typeError != null)
			{
				error += this.typeError + '\n';
			}
		}
	}
	return (error.length > 0) ? error : null;
};
mxMultiplicity.prototype.checkType = function(graph, value, type, attr, attrValue)
{
	if (value != null)
	{
		if (!isNaN(value.nodeType))
		{
			return mxUtils.isNode(value, type, attr, attrValue);
		}
		else
		{
			return value == type;
		}
	}
	return false;
};